package com.cruise.oauth.controller;


import cn.hutool.core.util.ObjectUtil;
import com.cruise.common.core.constant.AuthConstants;
import com.cruise.common.web.result.Result;
import com.cruise.common.redis.helper.RedisHelper;
import com.cruise.oauth.bean.Oauth2Token;
import com.cruise.oauth.util.StringUtil;
import com.cruise.system.userapi.feignapi.FeignSystemApi;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import java.security.Principal;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.cruise.common.core.constant.AuthConstants.SENT_TIP;
import static com.cruise.common.core.constant.AuthConstants.VERIFICATION_CODE;

/**
 * @author cruise
 */
@Api(tags = "认证中心")
@RestController
@RequestMapping("/oauth")
@AllArgsConstructor
@Slf4j
public class AuthController {


    @Autowired
    private FeignSystemApi feignSystemApi;

    static Logger logger= LoggerFactory.getLogger(AuthController.class);
    private TokenEndpoint tokenEndpoint;

    private RedisTemplate redisTemplate;

    @Resource
    private RedisHelper redisHelper;


    @ApiOperation("OAuth2认证生成token")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "grant_type", defaultValue = "password", value = "授权模式", required = true),
            @ApiImplicitParam(name = "client_id", defaultValue = "client", value = "Oauth2客户端ID", required = true),
            @ApiImplicitParam(name = "client_secret", defaultValue = "123456", value = "Oauth2客户端秘钥", required = true),
            @ApiImplicitParam(name = "refresh_token", value = "刷新token"),
            @ApiImplicitParam(name = "username", defaultValue = "admin", value = "登录用户名"),
            @ApiImplicitParam(name = "password", defaultValue = "123456", value = "登录密码"),

            @ApiImplicitParam(name = "code", value = "小程序code"),
            @ApiImplicitParam(name = "encryptedData", value = "包括敏感数据在内的完整用户信息的加密数据"),
            @ApiImplicitParam(name = "iv", value = "加密算法的初始向量"),
    })
    @PostMapping("/token")
    public Result postAccessToken(
            @ApiIgnore Principal principal,
            @ApiIgnore @RequestParam Map<String, String> parameters
    ) throws HttpRequestMethodNotSupportedException {
        String clientId = parameters.get("client_id");
        switch (clientId) {
            case AuthConstants.WEAPP_CLIENT_ID:
                // 微信认证
                // return this.handleForWxAuth(principal, parameters); 后期实现
            default:
                OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
                Oauth2Token oauth2Token = Oauth2Token.builder()
                        .token(oAuth2AccessToken.getValue())
                        .refreshToken(oAuth2AccessToken.getRefreshToken().getValue())
                        .expiresIn(oAuth2AccessToken.getExpiresIn())
                        .build();
                return Result.success(oauth2Token);
        }
    }


    /**
     * 随机生成 四位数字，
     * 发送给 phoneNumber
     * 存入redis，有效时间为10分钟
     * 如果 该手机号的短信验证码还没有过期（redis 里面还有值）不发送短信，但会同样提示已发送
     * @param phoneNumber
     * @return
     */
    @ApiOperation("生成短信验证码")
    @PostMapping("/getVerificationCode")
    public Result getVerificationCode(@RequestParam("phoneNumber") String phoneNumber){

        //验证手机号是否存在
        if(!feignSystemApi.checkPhoneAvailable(phoneNumber)){
            return Result.failed("手机号不存在");
        }
        //如果 该手机号的短信验证码还没有过期（redis 里面还有值）不发送短信，但会同样提示已发送
        Object o = redisTemplate.opsForValue().get(VERIFICATION_CODE + phoneNumber);
        if(!ObjectUtil.isNull(o)){
            logger.info("缓存中手机号：{} 的短信验证码：{}",phoneNumber, o.toString());
            // 生产环境请更改
            return Result.success("测试：缓存中手机号："+ phoneNumber +" 的短信验证码："+o.toString() +" " + SENT_TIP);
        }
        // 产生4位随机数字
        String verificationCode = StringUtil.getVerificationCode();
        // 手机号 与 数字绑定 存入redis中，设置有效期10 分钟
        redisTemplate.opsForValue().set(VERIFICATION_CODE + phoneNumber, verificationCode, 60 * 10, TimeUnit.SECONDS);
        // 发送短信 ... 待介入电信运营商

        logger.info("手机号：{} 的短信验证码：{}",phoneNumber, verificationCode);

        // // 生产环境请更改
        return Result.success("测试：手机号：" + phoneNumber + " 的短信验证码：" + verificationCode + " " + SENT_TIP);
    }

}
